package ar.com.spsolutions.splibrary.library;

import java.util.Set;

import ar.com.spsolutions.splibrary.author.Author;
import ar.com.spsolutions.splibrary.book.Book;
import ar.com.spsolutions.splibrary.dashboard.DashBoard;
import ar.com.spsolutions.splibrary.notifiers.INotifier;
import ar.com.spsolutions.splibrary.user.User;
import ar.com.spsolutions.splibrary.user.exception.CustomerRentExceeded;
import ar.com.spsolutions.splibrary.user.role.UserRole;
import ar.com.spsolutions.splibrary.user.role.exceptions.UnprivilegedUserException;
import ar.com.spsolutions.splibrary.utils.PasswordUtil;

public class Library {

	private User user;

	private transient INotifier notifier;

	private Set<User> userSet;

	public Library(final INotifier aNotifier) {
		this.notifier = aNotifier;
		this.user = this.createFirstUser();
	}

	public Library(final User user, final INotifier aNotifier) {
		this.user = user;
		this.notifier = aNotifier;
	}

	public void makeComment(final User customer, final Book book,
			final String comment) {
		book.addComment(customer, comment);
	}

	public void reserveBook(final Book book, final User customer) {
		this.checkPrivilegies();
		book.reservedFor(customer);
	}

	public void loanBook(final User customer, final Book book) {
		this.checkPrivilegies();
		if (!customer.canRentAnotherBook()) {
			throw new CustomerRentExceeded("Ya exedio la cantidad de prestamos");
		}
		customer.addLoan(book.loanTo(customer));
	}

	public void createCopiesOf(final Book book, final int amount) {
		this.checkPrivilegies();
		book.createCopies(amount);
	}

	public Book createBook(final String title, final Author author,
			final String isbn, final String editorial) {
		this.checkPrivilegies();
		final Book book = new Book(this.getNotifier());
		book.setTitle(title);
		// book.setAuthors(author);
		book.setIsbn(isbn);
		book.setPublisher(editorial);
		return book;
	}

	private INotifier getNotifier() {
		return this.notifier;
	}

	public User createUser(final String newName, final String newEmail,
			final UserRole role) {
		this.checkPrivilegies();
		final User aUser = this.createUser0(newName, newEmail, role);
		this.notifyUserCreation(aUser);
		return aUser;
	}

	private User createUser0(final String newName, final String newEmail,
			final UserRole role) {
		final User aUser = new User();
		aUser.setName(newName);
		aUser.setPassword(PasswordUtil.getPassword(16));
		aUser.setEmail(newEmail);
		aUser.setRole(role);
		return aUser;
	}

	private User createFirstUser() {
		final User aUser = this.createUser0("root", "leezsi@hotmail.com",
				UserRole.librarian());
		aUser.setPassword("roottt");
		this.notifyUserCreation(aUser);
		return aUser;
	}

	private void notifyUserCreation(final User anUser) {
		this.getNotifier().setRecipient(anUser);
		this.getNotifier().setSubject("Bienvenido a spLibrary");
		final String mailMessage = "Estimado %s, \n\t "
				+ "Queremos darle la gracias por formar parte de nuestra biblioteca.\n"
				+ "\nTambien le informamos el password suministrado para usted es %s y que deberia de cambiarlo.";
		this.getNotifier().setMessage(
				String.format(mailMessage, anUser.getName(),
						anUser.getPassword()));
		this.getNotifier().sendNotification();
	}

	public void notifyDebt2Users() {
		this.getDashBoard(this.getUserSet()).notifyDues();
	}

	public DashBoard getDashBoard(final Set<User> users) {
		this.checkPrivilegies();
		return new DashBoard(users, this.getNotifier());
	}

	private void checkPrivilegies() {
		if (!this.getUser().isAdmin()) {
			throw new UnprivilegedUserException("The user is not a libraryan");
		}
	}

	// ---accesors---
	public User getUser() {
		return this.user;
	}

	public void setUser(final User user) {
		this.user = user;
	}

	public Set<User> getUserSet() {
		return this.userSet;
	}

	public void setUserSet(final Set<User> userSet) {
		this.userSet = userSet;
	}

	public static Library initialize(final INotifier aNotifier) {
		return new Library(aNotifier);
	}

	public void createUser(final User anUser) {
		this.notifyUserCreation(anUser);
	}

}
